﻿//TradersPanel.xaml.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Xaml
{
	using System;
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.Linq;
	using System.Windows;
	using System.Windows.Controls;
	using System.Windows.Input;
	using System.Windows.Media.Imaging;

	using Ecng.Collections;
	using Ecng.Common;
	using Ecng.ComponentModel;
	using Ecng.Serialization;
	using Ecng.Xaml;

	using StockSharp.Algo;
	using StockSharp.Algo.Testing;
	using StockSharp.BusinessEntities;

	/// <summary>
	/// Панель создания новых шлюзов <see cref="ITrader"/>.
	/// </summary>
	public partial class TradersPanel
	{
		private sealed class TraderRow : NotifiableObject
		{
			public TraderRow(ITrader trader, string title)
			{
				if (trader == null)
					throw new ArgumentNullException("trader");

				Trader = trader;
				Title = title;
				IsEnabled = true;
			}

			private ITrader _trader;

			public ITrader Trader
			{
				get { return _trader; }
				set
				{
					if (value == null)
						throw new ArgumentNullException("value");

					_trader = value;
					IsEmulator = value is RealTimeEmulationTrader;
					RefreshDescription();
				}
			}

			public string Title { get; private set; }

			public string Description
			{
				get
				{
					return Trader.DisplayName;
				}
			}

			private bool _isEnabled;

			public bool IsEnabled
			{
				get { return _isEnabled; }
				set
				{
					_isEnabled = value;
					NotifyChanged("IsEnabled");
				}
			}

			public bool IsEmulator { get; private set; }

			public void RefreshDescription()
			{
				NotifyChanged("Description");
			}
		}

		private sealed class TradeInfoList : BaseList<Tuple<string, Type, Type>>
		{
			private readonly TradersPanel _parent;
			private readonly Dictionary<Tuple<string, Type, Type>, MenuItem> _items = new Dictionary<Tuple<string, Type, Type>, MenuItem>();

			public TradeInfoList(TradersPanel parent)
			{
				if (parent == null)
					throw new ArgumentNullException("parent");

				_parent = parent;
			}

			protected override bool OnAdding(Tuple<string, Type, Type> item)
			{
				var traderType = item.Item2;
				var panelType = item.Item3;

				var mi = new MenuItem
				{
					Header = item.Item1,
				};

				mi.Click += (sender, args) =>
				{
					var wnd = new TraderWindow
					{
						SettingsPanel = panelType.CreateInstance<ITraderSettingsPanel>(),
						Trader = traderType.CreateInstance<ITrader>(),
					};

					if (!wnd.ShowModal(_parent))
					{
						wnd.Trader.Dispose();
						return;
					}

					_parent._traders.Add(wnd.Trader);
					_parent._traders[wnd.Trader] = 0;

					_parent._traderRows.Add(new TraderRow(wnd.Trader, item.Item1));
				};

				_items.Add(item, mi);
				_parent.ConnectionsMenu.Items.Add(mi);

				return base.OnAdding(item);
			}

			protected override bool OnRemoving(Tuple<string, Type, Type> item)
			{
				_parent.ConnectionsMenu.Items.Remove(_items[item]);
				_items.Remove(item);
				return base.OnRemoving(item);
			}

			protected override bool OnClearing()
			{
				_parent.ConnectionsMenu.Items.Clear();
				_items.Clear();
				return base.OnClearing();
			}
		}

		/// <summary>
		/// 
		/// </summary>
		public static RoutedCommand RemoveTraderCommand = new RoutedCommand();

		/// <summary>
		/// 
		/// </summary>
		public static RoutedCommand EnableTraderCommand = new RoutedCommand();

		private readonly ObservableCollection<TraderRow> _traderRows = new ObservableCollection<TraderRow>();

		/// <summary>
		/// Создать <see cref="TradersPanel"/>.
		/// </summary>
		public TradersPanel()
		{
			InitializeComponent();

			TradersGrid.ItemsSource = _traderRows;
			_traderInfo = new TradeInfoList(this);
		}

		private BasketTrader _trader;

		/// <summary>
		/// Шлюз-агрегатор.
		/// </summary>
		public BasketTrader Trader
		{
			get { return _trader; }
			set
			{
				_trader = value;
				Traders = value == null ? null : value.InnerTraders;
			}
		}

		private BasketTrader.IInnerTraderList _traders;

		/// <summary>
		/// Коллекция шлюзов.
		/// </summary>
		public BasketTrader.IInnerTraderList Traders
		{
			get { return _traders; }
			set
			{
				_traders = value;

				_traderRows.Clear();

				if (_traders == null)
					return;

				_traderRows.AddRange(_traders.Select(t => new TraderRow(t, GetInfo(t).Item1) { IsEnabled = _traders[t] != -1 }));
			}
		}

		private readonly IList<Tuple<string, Type, Type>> _traderInfo;

		/// <summary>
		/// Визуальное описание доступных шлюзов.
		/// </summary>
		public IList<Tuple<string, Type, Type>> TraderInfo
		{
			get { return _traderInfo; }
		}

		private Tuple<string, Type, Type> GetInfo(ITrader trader)
		{
			if (trader == null)
				throw new ArgumentNullException("trader");

			trader = trader is RealTimeEmulationTrader ? ((RealTimeEmulationTrader)trader).UnderlyingTrader : trader;
			return TraderInfo.First(i => i.Item2.IsInstanceOfType(trader));
		}

		private TraderRow SelectedInfo
		{
			get { return TradersGrid != null ? (TraderRow)TradersGrid.SelectedItem : null; }
		}

		private bool CheckConnected(string message)
		{
			if (SelectedInfo.Trader.IsConnected)
			{
				new MessageBoxBuilder()
					.Owner(this.GetWindow())
					.Warning()
					.Text(message)
						.Show();

				return false;
			}

			return true;
		}

		private void ExecutedRemoveTrader(object sender, ExecutedRoutedEventArgs e)
		{
			if (!CheckConnected("Нельзя удалить подключенное соединение."))
				return;

			_traders.Remove(SelectedInfo.Trader);
			SelectedInfo.Trader.Dispose();
			_traderRows.Remove(SelectedInfo);
		}

		private void CanExecuteRemoveTrader(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = SelectedInfo != null;
		}

		private void TradersGrid_DoubleClick(object sender, MouseButtonEventArgs e)
		{
			if (SelectedInfo == null)
				return;

			if (!CheckConnected("Нельзя редактировать подключенное соединение."))
				return;

			var emuTrader = SelectedInfo.Trader as RealTimeEmulationTrader;
			var trader = emuTrader == null ? SelectedInfo.Trader : emuTrader.UnderlyingTrader;

			var wnd = new TraderWindow
			{
				SettingsPanel = GetInfo(trader).Item3.CreateInstance<ITraderSettingsPanel>(),
				Trader = trader.Clone()
			};

			if (!wnd.ShowModal(this))
				return;

			trader.Load(wnd.Trader.Save());

			SelectedInfo.RefreshDescription();
		}

		private void IsEmulatorCtrl_Click(object sender, RoutedEventArgs e)
		{
			if (!CheckConnected("Нельзя изменять статус эмуляции в подключенном состоянии. Необходимо в начале отключиться."))
				return;

			var trader = SelectedInfo.Trader;

			var priority = _traders[trader];
			_traders.Remove(trader);

			var emuTrader = trader as RealTimeEmulationTrader;
			trader = SelectedInfo.Trader = emuTrader == null ? new RealTimeEmulationTrader(trader) : emuTrader.UnderlyingTrader;
			_traders.Add(trader);
			_traders[trader] = priority;
		}

		private void TradersGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			if (SelectedInfo != null)
			{
				ChangeDisableEnableIcon(SelectedInfo.IsEnabled);

				IsEmulatorCtrl.IsEnabled = true;
				IsEmulatorCtrl.IsChecked = SelectedInfo.IsEmulator;
			}
			else
			{
				ChangeDisableEnableIcon(false);

				IsEmulatorCtrl.IsEnabled = false;
				IsEmulatorCtrl.IsChecked = false;
			}
		}

		private void ExecutedEnableTrader(object sender, ExecutedRoutedEventArgs e)
		{
			if (!CheckConnected("Нельзя изменять статус соединения в подключенном состоянии. Необходимо в начале отключиться."))
				return;

			SelectedInfo.IsEnabled = !SelectedInfo.IsEnabled;
			_traders[SelectedInfo.Trader] = SelectedInfo.IsEnabled ? 0 : -1;

			ChangeDisableEnableIcon(SelectedInfo.IsEnabled);
		}

		private void CanExecuteEnableTrader(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = SelectedInfo != null;
		}

		private void ChangeDisableEnableIcon(bool isEnabled)
		{
			var bmp = EnableImg;
			bmp.Source = new BitmapImage(new Uri("pack://application:,,,/StockSharp.Xaml;component/Images/" + (isEnabled ? "disabled.png" : "enabled.png")));
			bmp.InvalidateMeasure();
			bmp.InvalidateVisual();
			bmp.SetToolTip(isEnabled ? "Отключить подключение" : "Включить подключение");
		}
	}
}
